package com.midian.common.interceptor;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;

import com.midian.common.annotation.FileModelDetails;
import com.midian.common.exception.BizException;
import com.midian.common.exception.ModelException;
import com.midian.common.utils.PicUtils;
import com.midian.model.common.FileModel;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

/**
 * 文件上传拦截器
 * @author Mengfh
 *
 */
public class FileUploadInterceptor extends MethodFilterInterceptor {
	
	private static final long serialVersionUID = -7384892069714292473L;
	private PicUtils picUtils;
	@Resource(name="picUtils")
	public void setPicUtils(PicUtils picUtils) {
		this.picUtils = picUtils;
	}

	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		//获取目标Action对象
		Object action = invocation.getAction();
		//获取Action方法名
		//String methodName = invocation.getProxy().getMethod();
		//获取Action中文件模型的get方法
		List<Method> fileModelMethodList = new ArrayList<Method>();
		Method[] methods = action.getClass().getDeclaredMethods();
		for (Method method : methods) {
			if(FileModel.class.equals(method.getReturnType()) && method.getName().startsWith("get")) {
				fileModelMethodList.add(method);
			}
		}
		for (Method fileModelMethod : fileModelMethodList) {
			if(fileModelMethod.isAnnotationPresent(FileModelDetails.class)) {
				FileModelDetails fileModelDetails = fileModelMethod.getAnnotation(FileModelDetails.class);
				String objName = fileModelDetails.objName(); //对象名称
				Object obj = action.getClass().getMethod("get" + objName.substring(0, 1).toUpperCase() + objName.substring(1)).invoke(action);
				String fieldName = fileModelDetails.fieldName(); //获取需要更新的实体属性名称
				FileModel fileModel = (FileModel) fileModelMethod.invoke(action);
				boolean isDelOldFile = fileModelDetails.isDelOldFile();
				try {
					uploadFile(obj, fileModel, fieldName, isDelOldFile);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return invocation.invoke();
	}
	
	/**
	 * 上传文件
	 * @param fileModel 文件模型对象
	 * @param modulePath 模块路径
	 * @param fieldName 路径属性名
	 * @throws BizException
	 */
	private void uploadFile(Object entity, FileModel fileModel, String fieldName,boolean isDelOldFile) throws BizException {
		if(fileModel != null && fileModel.getFile() != null && entity != null) {
			try {
				String oldPicId = "";
				Object result=getPropertyValue(entity, fieldName);
				if(result != null){
					oldPicId = String.valueOf(result);//获取图片的id值
				}
				setPropertyValue(entity, fieldName, picUtils.uploadPic(fileModel.getFile(),fileModel.getFileFileName()));//上传图片并赋值给对象对应的值
				if(isDelOldFile && StringUtils.isNotBlank(oldPicId)){//删除旧图片
					picUtils.deletePic(oldPicId);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private static void setPropertyValue(Object entity, String property, Object val) throws Exception {
		String[] propNames = property.split("\\."); //拆分属性链
		Object lastObj = entity; //将上一对象默认保存为根对象（同一个map使用同一个根对象）
		for(int i = 0; i < propNames.length; i++) {
			String propName = propNames[i]; //获取属性
			String getMethodName = "get" + propName.substring(0, 1).toUpperCase() + propName.substring(1); //获取属性的get方法名称
			Method getMethod = lastObj.getClass().getMethod(getMethodName); //获取属性的get方法对象
			Class<?> paramType = lastObj.getClass().getMethod(getMethodName).getReturnType(); //获取get方法的返回值
			String setMethodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1); //获取set方法名称
			Method setMethod = lastObj.getClass().getMethod(setMethodName, paramType); //获取set方法对象
			
			Object paramVal = null; //参数值
			//如果已到达属性链尾部（即链中的最后一个属性），直接从map中获取属性的值
			if(i == propNames.length - 1) {
				paramVal = val;
			} else {
			//如果没到达属性链尾部，先通过get方法尝试获取该对象
				paramVal = getMethod.invoke(lastObj);
				//如果通过get方法获取对象为空，新建一个对象，并通过set方法将对象设置到前一对象中
				if(paramVal == null) {
					paramVal = paramType.newInstance();
				}
			}
			setMethod.invoke(lastObj, paramVal);
			lastObj = paramVal;
		}
	}
	
	private static String convertDateToStr(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(date);
	}
	
	/**
	 * 
	 * @ClassName: ExcelHelper.java
	 * @Description: 获取属性链值
	 * @Author:Jiangjb
	 * @CreateDate:2013-6-7 下午3:35:03
	 * @param obj 目标对象
	 * @param property 属性
	 * @return
	 */
	private static Object getPropertyValue(Object obj,String property){
		String[] propertyChain = property.split("\\.");//获取属性链
		Object result = null;
		for (String pro : propertyChain) {
			if(obj==null){
				break;
			}
			String methodName = "get"+pro.substring(0,1).toUpperCase()+pro.substring(1);
			Class cl = obj.getClass();
			try {
				Method method = cl.getMethod(methodName, null);
				result = method.invoke(obj, null);
				//如果result为日期类型，将日期转换为字符串类型(防止导出后转换为24小时的问题)
				if(result instanceof Date) {
					Date date = (Date) result;
					result = convertDateToStr(date);
				}
				////System.out.println(methodName+":"+result);
				if(result!=null){
					String resultStr = result.toString().trim();
					if(!resultStr.equals("")){
						obj = result;
						continue;
					}
				}
				result = null;
				obj = null;
			} catch (Exception e) {
				//e.printStackTrace();
				throw new ModelException("不存在该方法 "+methodName);
			}
		}
		return result;
	}
}
